#!/usr/bin/python2.5
#
# (c) 2010 - Chip Turner
#
# Apache License, blah blah, it's a few hundred lines of python.

import cookielib
import logging
import os
import time
import getpass
import urllib
import urllib2
import mechanize
from xml.etree import ElementTree

try:
  import json
except ImportError:
  import simplejson as json
            
import armory_lib

class AuctionHouseInterface(object):
  def __init__(self, region, account_name):
    self.region = region
    self.account_name = account_name
    self.cookie_filename = os.path.join(os.path.expanduser("~"), ".auction_lib_cookies")
    self.cookie_jar = cookielib.LWPCookieJar(filename=self.cookie_filename)
    self.cookie_jar.load()
    self.browser = mechanize.Browser(factory=mechanize.DefaultFactory(i_want_broken_xhtml_support=True))
    self.browser.addheaders.append(('User-agent', armory_lib.USER_AGENT))
    self.browser.set_cookiejar(self.cookie_jar)
    self.throttle = armory_lib.Throttle()
    self.throttle.max_req_per_second = 0.5
    self.throttle.initial_burst_max = 1
    

  def Login(self):
    success = False
    while not success:
      p = getpass.getpass("Enter password for %s: " % self.account_name)
      url = 'https://us.battle.net/login/login.xml?ref=http://us.wowarmory.com/auctionhouse/index.xml&app=armory&cr=true'

      logging.info("Fetching %s", url)
      response = self.browser.open(url)
      content = response.read()
      form = self.browser.select_form(nr=0)
      self.browser["accountName"] = self.account_name
      self.browser["password"] = p
      response = self.browser.submit()

      if response.geturl().startswith('https://us.battle.net/login/authenticator.html'):
        a = getpass.getpass("Authenticator code: ")
        form = self.browser.select_form(nr=0)
        self.browser['authValue'] = a
        response = self.browser.submit()

      if response.geturl().startswith('http://us.wowarmory.com/auctionhouse/index.xml'):
        success = True

    logging.debug("Saving cookies")
    self.cookie_jar.save()

  def ChangeHouse(self, house):
    assert house in "nah"
    url = "http://us.wowarmory.com/auctionhouse/faction.json?f=" + house
    overview = self.SmartFetch(url)
    print overview
    
  def ChangeCharacter(self, realm, toon):
    url = "http://us.wowarmory.com/vault/character-select-submit.json?cn=%s&r=%s" % (urllib.quote(toon), urllib.quote(realm))
    result = self.SmartFetch(url)
    return result

  def SmartFetch(self, url, retry=True):
    self.throttle.Check()
    logging.info("Fetching %s" % url)
    response = self.browser.open(url)
    data = response.read().replace("\\'", "'")
    json_result = json.loads(data)
    if "error" in json_result and json_result['error']['error'] and retry:
      logging.error("Error: %s" % json_result['error']['message'])
      if json_result['error']['code'] == 10005:
        logging.info("Logging in, retrying...")
        self.Login()
        return self.SmartFetch(url, retry=False)
    self.cookie_jar.save(ignore_discard=1)
    return json_result
    
  def SearchAuctionHouse(self, **kwargs):
    base_url = "http://us.wowarmory.com/auctionhouse/search.json?"
    params = list()
    for kw in kwargs:
      params.append("%s=%s" % (kw, urllib2.quote(kwargs[kw])))

    page_size = 40
    num_results = 0
    ret = list()
    while True:
      url = base_url + "&".join(params + ["pageSize=%d&start=%d" % (page_size, num_results)])
      results = self.SmartFetch(url)
      assert 'auctionSearch' in results
      results = results['auctionSearch']
      ret.extend(results['auctions'])
      if results['end'] == results['total']:
        break
      num_results += results['end'] - results['start']
    return ret
    
  def FindAllGlyphs(self):
    letters = range(ord('a'), ord('z') + 1)
    for letter in reversed(letters):
      glyphs = dict()
      results = self.SearchAuctionHouse(n="glyph of %c" % letter, sort='TIME', reverse='false')
      seen_ids = set()
      for auction in results:
        glyphs[auction['auc']] = auction
        seen_ids.add(auction['auc'])
      if len(seen_ids) == 200:
        logging.info("More than 200 results, trying reverse sort...")
        results = self.SearchAuctionHouse(n="glyph of %c" % letter, sort='TIME', reverse="true")
        for auction in results:
          glyphs[auction['auc']] = auction
          if auction['auc'] in seen_ids:
            break
        if len(seen_ids) == 400:
          logging.error("Forward and reverse sort of 'glyph of %c' did not overlap!  Some results missing" % letter)
      logging.info("Saw %d total glyphs for 'glyph of %c'" % (len(seen_ids), letter))
      for glyph in glyphs.values():
        yield glyph

